var dTableSorter = (function(dt, d, $, undefined) {
	d.require('dojo.NodeList-manipulate');
	d.require('dojo.NodeList-fx');	
	var settings,
	parsers = {},
	getSortFunction = function(colName) {
		for (var name in parsers) {
			if (settings.columns[name]) {
				if (d.indexOf(settings.columns[name], colName)  > -1) {
					var parser = parsers[name];
                    if (name !== undefined) {
						return parsers[name];
					}
				}
			}
		}
		throw new Error('No parser for column : ' + colName);
	},

	getColumns = function() {
		var cols = [];
		for (var name in settings.columns) {
			d.forEach(settings.columns[name],function(colName) {		
				cols.push(['#', colName].join(''));
			});
		}
		return cols.join(', ');	
	},

	getColIndex = function(colName) {
		var index = 0;
		d.some($(dt.node.get('th')), function(col) {
			index++;
			return col.id === colName;
		});
		return index;
	},

	ContentNode = function(node) {	
		this.node = ['#', node].join('');
        this.get = function(query) {
			if (!query) {
				return $(this.node);
			}
			return $([this.node, ' ', query].join(''));
		};
	},

	setupTableRows = function() {
		dt.node.get('tbody tr').onclick(function() {
			d.toggleClass(this,'dTableSorter-row-selected');
		})
        .onmouseover(function() {
			d.addClass(this, 'dTableSorter-row-hover');
		})
		.onmouseout(function() {
			d.removeClass(this, 'dTableSorter-row-hover');
		});
	},
	
	setupHeaderColumns = function(columns) {
		$(columns)
		 .addClass('dTableSorter-header-col')
		 .onmouseover(function() { d.addClass(this,'dTableSorter-column-hover'); })
		 .onmouseout(function() { d.removeClass(this,'dTableSorter-column-hover'); })
			.forEach(function(el, index) {
				d.connect(el, 'click', function() {
					$('.dTableSorter-header-col-choosen').removeClass('dTableSorter-header-col-choosen');
					d.addClass(el,'dTableSorter-header-col-choosen');
					d.toggleClass(el,'dTableSorter-sorted');
					var isSorted = !d.hasClass(el,'dTableSorter-sorted'),
						sortFunction = getSortFunction(el.id),
						sorted = d.map(dt.node.get('tbody tr td:nth-child('+(getColIndex(el.id))+')')
								  .sort(function(node1, node2) {
										var a = $(node1).text(), b = $(node2).text();
										return sortFunction(isSorted, a, b, node1, node2);
                                    }), function(el) { return el.parentNode; });
							dt.node.get('tbody tr').remove();
							dt.node.get('tbody').append(sorted);
						});
				});
       },

       setupTableSorter = function(id) {
			dt.node = new ContentNode(id);
			setupTableRows();
			setupHeaderColumns(getColumns());
       };

       dt.addParser = function(name, fn) {
			parsers[name] = fn;
       };

       dt.addParser('number', function(asc, a, b) {
			return asc ? a - b : b - a;
       });

       dt.addParser('string', function(asc, a, b) {
			return asc ? (b > a ? 1 : a === b ? 0 : -1) : (b < a ? 1 : a === b ? 0 : -1);
       });

       d.extend(d.NodeList, {
			dTableSorter : function(options) {
				var node = this[0];
				if (node === undefined || !('id' in node))  {
					throw new Error('Missing node id!');
				}
				settings = options;
				setupTableSorter(node.id);
				return this;
			}
		});

       return dt;

})(dTableSorter || {}, dojo, dojo.query, undefined);